package com.dd.stack.redis.service.inner.impl;

import com.dd.stack.redis.config.redisConfig.RedisKeyFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @Author liuxianmeng
 * @CreateTime 2025/1/31 23:15
 * @Description 排行榜服务
 */
@Service
public class LeaderboardServiceImpl {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate; // 改为 Object 类型

    /**
     * 添加或替换用户分数
     */
    public void addOrReplaceScore(Long userId, double score) {
        ZSetOperations<String, Object> zSetOps = redisTemplate.opsForZSet();
        zSetOps.add(RedisKeyFactory.userLeaderboardKey(), userId, score);
    }

    /**
     * 添加或累加用户分数
     */
    public void addOrIncreScore(Long userId, double score) {
        ZSetOperations<String, Object> zSetOps = redisTemplate.opsForZSet();
        zSetOps.incrementScore(RedisKeyFactory.userLeaderboardKey(), userId, score);
    }

    /**
     * 获取排行榜前N名（返回 Long 类型 Set）
     */
    public Set<Long> getTopRanks(int topN) {
        ZSetOperations<String, Object> zSetOps = redisTemplate.opsForZSet();
        Set<Object> rawResult = zSetOps.reverseRange(RedisKeyFactory.userLeaderboardKey(), 0, topN - 1);
        return convertToLongSet(rawResult);
    }

    /**
     * 获取用户排名
     */
    public Long getUserRank(Long userId) { // 参数改为 Long
        ZSetOperations<String, Object> zSetOps = redisTemplate.opsForZSet();
        Long rank = zSetOps.rank(RedisKeyFactory.userLeaderboardKey(), userId);
        return rank != null ? rank + 1 : null; // 排名从1开始
    }

    /**
     * 删除指定用户
     */
    public void removeUser(Long userId) { // 参数改为 Long
        redisTemplate.opsForZSet().remove(RedisKeyFactory.userLeaderboardKey(), userId);
    }

    /**
     * 将 Set<Object> 转换为 Set<Long>
     */
    private Set<Long> convertToLongSet(Set<Object> rawSet) {
        if (rawSet == null) {
            return Collections.emptySet();
        }
        return rawSet.stream()
                .map(obj -> {
                    if (obj instanceof Long) {
                        return (Long) obj;
                    } else if (obj instanceof Integer) {
                        return ((Integer) obj).longValue();
                    } else if (obj instanceof String) {
                        return Long.parseLong((String) obj);
                    }
                    throw new IllegalArgumentException("Unsupported type in leaderboard: " + obj.getClass());
                })
                .collect(Collectors.toSet());
    }
}
